package com.idea.id_generate.rest;

import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.Errors;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;


/**
 * ResponseEntityUtil
 */
public final class ResponseEntityUtil {

    private ResponseEntityUtil() {
    }

    /**
     * 请求成功
     *
     * @return ResponseEntity
     *  2018年4月19日 下午2:23:43
     */
    public static <T extends Serializable> ResponseEntity<T> success() {
        return new ResponseEntity<>(HttpStatus.OK);
    }

    /**
     * 请求成功
     *
     * @param model
     * @return ResponseEntity
     *  2018年4月19日 下午2:24:11
     */
    public static <T> ResponseEntity<T> success(T model) {
        return new ResponseEntity<>(model, HttpStatus.OK);
    }

    /**
     * 服务器找不到请求的资源
     *
     * @param model
     * @return ResponseEntity
     *  2018年4月19日 下午2:23:43
     */
    public static <T> ResponseEntity<ResponseWrapper<T>> notFound(T model) {
        return ResponseEntity.status(HttpStatus.NOT_FOUND)
                .body(ResponseWrapper.failed(model).setMessage("Requested resource not found").build());
    }

    /**
     * 服务器找不到请求的资源
     *
     * @return ResponseEntity
     *  2018年4月19日 下午2:35:09
     */
    public static <T> ResponseEntity<ResponseWrapper<T>> notFound() {
        return notFound(null);
    }

    /**
     * 请求成功并且服务器创建了新的资源
     *
     * @param model
     * @return ResponseEntity
     *  2018年4月19日 下午2:23:43
     */
    public static <T> ResponseEntity<T> created(T model) {
        return new ResponseEntity<T>(model, HttpStatus.CREATED);
    }

    public static <T> ResponseEntity<T> updated(T model) {
        return new ResponseEntity<T>(model, HttpStatus.CREATED);
    }

    /**
     * 拒绝访问
     *
     * @param model
     * @return ResponseEntity
     *  2018年4月19日 下午2:23:43
     */
    public static <T> ResponseEntity<T> forbidden(T model) {
        return new ResponseEntity<>(model, HttpStatus.FORBIDDEN);
    }

    /**
     * 自定义
     *
     * @param code
     * @return ResponseEntity
     *  2018年4月19日 下午2:23:43
     */
    public static <T> ResponseEntity<T> with(HttpStatus status) {
        return new ResponseEntity<>(status);
    }

    public static <T> ResponseEntity<T> with(HttpStatus status, T model) {
        return new ResponseEntity<>(model, status);
    }

    public static ResponseEntity<ResponseWrapper<?>> failed(HttpStatus status, ResponseWrapper<?> failureResponse) {
        return new ResponseEntity<>(failureResponse, status);
    }

    public static ResponseEntity<ResponseWrapper<?>> badRequest(HttpServletRequest request, Errors errors) {
        if (errors.hasErrors()) {
            List<String> errMessages = new ArrayList<>();
            errors.getAllErrors().forEach(err -> errMessages.add(err.getDefaultMessage()));
            return ResponseEntity.badRequest().body(ResponseWrapper.validationErrors(errors)
                    .code(ResponseCode.FAILED).build());
        } else {
            return null;
        }
    }

    public static ResponseEntity<ResponseWrapper<?>> exception(Throwable throwable, HttpStatus status,
                                                               HttpServletRequest request) {
        if (throwable != null) {
            return ResponseEntity.status(status)
                    .body(ResponseWrapper.exception().setMessage(ResponseEntityUtil.getRootCauseMessage(throwable))
                            .code(ResponseCode.FAILED).build());
        } else {
            return null;
        }
    }

    public static ResponseEntity<ResponseWrapper<?>> exception(int code, String messages, HttpStatus status,
                                                               HttpServletRequest request) {
        return ResponseEntity.status(status).body(ResponseWrapper.exception().setMessage(messages).code(code).build());
    }


    public static ResponseEntity<ResponseWrapper<?>> exception(int code, Throwable throwable, HttpStatus status,
                                                               HttpServletRequest request) {
        if (throwable != null) {
            return ResponseEntity.status(status)
                    .body(ResponseWrapper.exception().setMessage(ResponseEntityUtil.getRootCauseMessage(throwable))
                            .code(code).build());
        } else {
            return null;
        }
    }


    public static <T> ResponseEntity<ResponseWrapper<T>> exception(Throwable throwable, T data, HttpStatus status,
                                                                   HttpServletRequest request) {
        if (throwable != null) {
            return ResponseEntity.status(status)
                    .body(ResponseWrapper.exception(data)
                            .setMessage(ResponseEntityUtil.getRootCauseMessage(throwable)).code(-1)
                            .build());
        } else {
            return null;
        }
    }

    public static <T> ResponseEntity<ResponseWrapper<T>> exception(int code, Throwable throwable, T data,
                                                                   HttpStatus status, HttpServletRequest request) {
        if (throwable != null) {
            return ResponseEntity.status(status)
                    .body(ResponseWrapper.exception(data)
                            .setMessage(ResponseEntityUtil.getRootCauseMessage(throwable)).code(code)
                            .build());
        } else {
            return null;
        }
    }

    private static String getRootCauseMessage(Throwable throwable) {
        if (throwable != null) {
            Throwable root = ExceptionUtils.getRootCause(throwable);
            root = root == null ? throwable : root;
            return root.getLocalizedMessage();
        }
        return null;
    }
}
